function DataSet(sqlid) {
    this.isOpen = false;
    // 当前数据集中的数据
    this.datas = [];
    // 备份数据，用于出错回滚
    this.restores = {};
    // 当前数据集中的统计数据
    this.aggrs = {};
    // 当前数据集中的元数据
    this.metadatas = [];
    // sqlid值，如果不提供，不能使用open远程异步获取数据，只能使用setDatas同步操作
    this.sqlid = sqlid;
    // 是否跨越请求
    if (this.cors == null) {
        this.cors = this.baseURL.indexOf("http") == 0 && (!window.location.host || this.baseURL.indexOf(window.location.host) != 0);
    }
    // 是否合并每次查询的数据，而不是重置
    this.merge = false;
    // 唯一键
    this.key = "id";
    // 前端id，用于标记插入数据
    this.clientKey = "CLIENT_ROW_ID";
    // 查询参数
    this.params = {};
    // 第几页
    this.pageNo = 0;
    // 每页多少行
    this.pageSize = 50;
    // 总记录数
    this.recordcount = 0;
    // 总页数
    this.pages = 0;
    // 事件绑定
    this.beforeOpen = null;
    this.afterOpen = null;
    this.beforeClose = null;
    this.afterClose = null;
    this.onError = null;
    this.onInsert = null;
    this.onModify = null;
    this.onDelete = null;
    // 新增记录的Delta
    this.inserted = {};
    // 修改记录的Delta
    this.updated = {};
    // 删除记录的Delta
    this.deleted = {};
    // 是否输出数据调试信息
    this.debug = false;
}
// 定义数据集方法与
DataSet.prototype = {
    cors: null,
    // cilentId自动计数器
    cilentIdCounter: 0,
    // 输出参数映射
    parse: function(data) {
        var map = {
            outresult: null,
            outdesc: null,
            outdata: this.merge ? null : "datas",
            outmetadata: "metadatas",
            recordcount: "recordcount"
        };
        // 合并数据
        if (this.merge) {
            var key = this.key,
                datas = this.datas;
            outdata = data.outdata;
            for (var i = 0; i < outdata.length; i++) {
                var record = outdata[i],
                    unique = true;
                for (var j = 0; j < datas.length && unique; j++) {
                    if (record[key] == datas[j][key]) {
                        unique = false;
                        datas[j] = record;
                    }
                };
                if (unique) {
                    datas.push(record);
                }
            };
        }
        this.aggrs = {};
        for (key in data) {
            var item = data[key];
            key in map ? this[map[key]] = item : this.aggrs[key] = item;
        }
        if (this.pageNo > 0) {
            this.pages = Math.max(1, Math.ceil(this.recordcount / this.pageSize));
        }
        this.recordcount = parseInt(this.recordcount);
        this.restores = this._arrayToMap(this.datas);
    },
    // 排序
    sort: function(key, desc) {
        var f = desc ? -1 : 1;
        if (key == null) {
            key = this.key
        }
        this.datas.sort(function(a, b) {
            return f * (a[key] - b[key]);
        });
    },
    baseURL: "http://10.20.1.47:8082/IXWebService/dataService",
    // 打开数据集
    open: function() {
        var dataset = this;
        var param = {
            sqlid: dataset.sqlid,
            params: dataset.params,
            pageSize: dataset.pageSize,
            pageNo: dataset.pageNo,
            m: "querydata",
            s: "JSON"
        };
        dataset.beforeOpen && dataset.beforeOpen();
        dataset.debug && console.log(param);
        return $.ajax({
            url: this.baseURL,
            type: this.cors ? "GET" : "POST",
            dataType: this.cors ? "jsonp" : "json",
            cache: false,
            data: {
                allparams: JSON.stringify(param)
            },
            success: function(data) {
                dataset.debug && console.log(data);
                if (data.outresult === 'success') {
                    dataset.parse(data);
                    dataset.isOpen = true;
                    dataset.afterOpen && dataset.afterOpen(dataset.datas, dataset.metadatas, dataset.aggrs, data);
                } else if (data.outresult === 'error') {
                    console.error(data.outdesc || "未知错误");
                    dataset.onError && dataset.onError();
                }
            },
            error: function(data) {
                console.error(arguments);
                dataset.onError && dataset.onError();
            }
        });
    },
    // 关闭数据集，清空数据
    close: function() {
        if (this.beforeClose != null) {
            this.beforeClose();
        }
        this.datas = [];
        this.metadatas = [];
        this.aggrs = {};
        this.restores = {};
        this.inserted = {};
        this.updated = {};
        this.deleted = {};
        if (this.pageNo > 0) {
            this.pageNo = 1;
        }
        this.recordcount = 0;
        this.pages = 0;
        this.isOpen = false;
        if (this.afterClose != null) {
            this.afterClose();
        }
    },
    /**
     * 替换数据，用于同步设置数据
     * @param {Array} datas     数据
     * @param {Array} metadatas 标记数据
     * @param {Object} aggrs     其它属性例如recordcount和统计参数
     */
    setDatas: function(datas, metadatas, aggrs) {
        var data = $.extend({
            outdata: datas || [],
            outmetadata: metadatas || []
        }, aggrs);
        this.beforeOpen && this.beforeOpen();
        this.parse(data);
        this.isOpen = true;
        this.afterOpen && this.afterOpen(this.datas, this.metadatas, this.aggrs, data);
    },
    // 从另一个dataset复制全部数据
    copy: function(dataset) {
        this.setDatas(dataset.datas, dataset.metadatas, dataset.aggrs);
    },
    // 获取单条记录
    get: function(id) {
        var key = this.key;
        for (var i = 0; i < this.datas.length; i++) {
            var item = this.datas[i];
            if (item[key] == id) {
                return $.extend({}, item);
            }
        };
    },
    // 条件查询
    filter: function(filter) {
        return $.grep(this.datas, function(item) {
            return filter(item);
        });
    },
    // 指定页
    gotoPage: function(pageNo) {
        if (!this.isOpen) {
            console.error("数据集没有打开，不能取得数据!");
            return;
        }
        if (pageNo < 1 || pageNo > this.pages) {
            console.error("参数超出分页范围！");
            return;
        }
        this.pageNo = pageNo;
        return this.open();
    },
    // 首页
    firstPage: function() {
        return this.gotoPage(1);
    },
    // 上一页
    priorPage: function() {
        return this.gotoPage(this.pageNo - 1);
    },
    // 下一页
    nextPage: function() {
        return this.gotoPage(this.pageNo + 1);
    },
    // 末页
    endPage: function() {
        return this.gotoPage(this.pages);
    },
    // 新增记录
    addRecord: function(record) {
        var key = this.key;
        if (record[key] >= 0) {
            console.warn("记录带有唯一性标记属性（id），不能插入，改为修改", record);
            return this.modifyRecord(record);
        } else {
            var id = this._getNewCid();
            record[key] = id;
            this.inserted[id] = record;
            this.datas.push(record);
            this.onInsert && this.onInsert(record);
        }
        return true;
    },
    // 修改记录
    modifyRecord: function(record) {
        var key = this.key,
            id = record[key],
            isInsert = id < 0,
            modifyIn = isInsert ? "inserted" : "datas",
            modifyData = this[modifyIn],
            modifiedRecord,
            modified = false;
        if (id == null) {
            console.warn("记录没有唯一性标记属性（id），不能修改，改为插入", record);
            return this.addRecord(record);
        } else {
            if (isInsert) {
                modifiedRecord = $.extend(this.inserted[id], record);
            } else {
                item = this.get(id);
                for (var i = 0; i < this.datas.length; i++) {
                    var item = this.datas[i];
                    if (item[key] == id) {
                        for (k in record) {
                            modified = modified || (record[k] != null && record[k] != item[k]);
                        }
                        modifiedRecord = $.extend({}, item, record);
                        if (modified) {
                            this.updated[id] = this.datas[i] = modifiedRecord;
                        }
                        break;
                    }
                };
            }
            if (modifiedRecord) {
                this.onModify && this.onModify(modifiedRecord);
            } else {
                console.warn("尝试修改当前数据集中不存在的记录，可能导致失败", record);
            }
        }
        return modified;
    },
    /**
     * 删除记录
     * @param  {Object} or {String} record 要删除的记录或者id
     * @return {Bollean} 是否删除成功
     */
    deleteRecord: function(record) {
        var key = this.key,
            id = typeof record == "object" ? record[key] : record,
            isInsert = id < 0,
            deletedRecord;
        if (isInsert) {
            delete this.inserted[id];
        } else {
            delete this.updated[id];
            this.deleted[id] = record;
        }
        this.datas = $.grep(this.datas, function(item) {
            var deleted = item[key] == id;
            deleted && (deletedRecord = item);
            return !deleted;
        });
        if (deletedRecord) {
            this.onDelete && this.onDelete(deletedRecord);
        } else {
            console.warn("尝试删除当前数据集中不存在的记录，可能导致失败", record);
        }
        return !!deletedRecord;
    },
    // 回滚记录
    restoreRecord: function(record) {
        var key = this.key,
            clientKey = this.clientKey,
            id = typeof record == "object" ? record[key] : record,
            cid = record[clientKey];
        if (cid != null) {
            // 有cid的删除
            this.datas = $.grep(this.datas, function(item) {
                return item[key] != cid;
            });
        } else {
            this.mergeRecord(this.restores[id]);
        }
    },
    // 合并记录，但不产生修改记录
    mergeRecord: function(record) {
        var key = this.key,
            clientKey = this.clientKey,
            id = record[clientKey] || record[key],
            modified = false;
        for (var i = 0; i < this.datas.length; i++) {
            var item = this.datas[i],
                iid = item[key];
            if (iid == id) {
                record = $.extend(item, record);
                modified = true;
                break;
            }
        };
        delete record[clientKey];
        if (!modified) {
            this.datas.push(record);
        }
    },
    // 保存
    save: function() {
        var dataset = this,
            inserted = this._mapToArray(dataset.inserted),
            updated = this._mapToArray(dataset.updated),
            deleted = this._mapToArray(dataset.deleted),
            param = {
                sqlid: dataset.sqlid,
                params: {
                    inserted: inserted,
                    updated: updated,
                    deleted: deleted
                },
                m: "savedata",
                s: "JSON"
            };
        if (inserted.length > 0 || updated.length > 0 || deleted.length > 0) {
            if (!this.isOpen) {
                console.warn("数据集没有打开，记录数和统计信息可能出错");
            }
            dataset.beforeOpen && dataset.beforeOpen();
            dataset.debug && console.log(param);
            return $.ajax({
                url: this.baseURL,
                type: this.cors ? "GET" : "POST",
                dataType: this.cors ? "jsonp" : "json",
                cache: false,
                data: {
                    allparams: JSON.stringify(param)
                },
                success: function(data) {
                    dataset.debug && console.log(data);
                    if (data.outresult === 'success') {
                        var outdata = data.outdata,
                            clientKey = dataset.clientKey,
                            mergeData = (outdata.inserted || []).concat(outdata.updated || []),
                            deletedData = outdata.deleted || [],
                            addedRecordCount = 0;
                        // 合并插入，修改数据
                        for (var i = 0; i < mergeData.length; i++) {
                            var record = mergeData[i];
                            if (record.result == 1) {
                                if (record[clientKey] != null) {
                                    addedRecordCount++;
                                }
                                dataset.mergeRecord(record);
                            } else {
                                // 回滚失败数据
                                dataset.restoreRecord(record);
                                console.error(record.error || "未知错误", record);
                            }
                        };
                        dataset.inserted = {};
                        dataset.updated = {};
                        // 合并删除数据
                        for (var i = 0; i < deletedData.length; i++) {
                            var record = deletedData[i];
                            if (record.result == 1) {
                                addedRecordCount--;
                            } else {
                                // 回滚失败数据
                                dataset.restoreRecord(record);
                                console.error(record.error || "未知错误", record);
                            }
                        };
                        dataset.deleted = {};
                        dataset.restores = dataset._arrayToMap(dataset.datas);
                        // 更新数据计数
                        dataset.recordcount = Math.max(dataset.recordcount + addedRecordCount, 0);
                        dataset.isOpen = true;
                        dataset.afterOpen && dataset.afterOpen(dataset.datas, dataset.metadatas, dataset.aggrs, data);
                    } else if (data.outresult === 'error') {
                        console.error(data.outdesc || "未知错误");
                        dataset.onError && dataset.onError();
                    }
                },
                error: function(data) {
                    console.error(arguments);
                    dataset.onError && dataset.onError();
                }
            });
        } else {
            console.warn("没有需要保存的数据");
        }
    },
    // 生成客户端id
    _getNewCid: function() {
        return --this.cilentIdCounter;
    },
    _mapToArray: function(map) {
        var arr = [],
            key = this.key,
            clientKey = this.clientKey;
        for (k in map) {
            var record = $.extend({}, map[k]);
            if (record[key] < 0) {
                // 把负的id转换为clientId
                record[clientKey] = record[key];
                delete record[key];
            }
            arr.push(record);
        }
        return arr;
    },
    _arrayToMap: function(arr) {
        var map = {},
            key = this.key,
            clientKey = this.clientKey;
        for (var i = 0; i < arr.length; i++) {
            var item = arr[i],
                id = item[key];
            map[id] = item;
        };
        return map;
    }
};